/**
 * @file    gt98xx_drv_timer.c
 * @author  Giantec-Semi ATE
 * @brief   Source file of TIMER driver module.
 * @version 0.1
 * 
 * @copyright Copyright (c) 2021 Giantec-Semi
 */
#include "gt98xx_drv_timer.h"

/**
 * @addtogroup GT98xx_DRV
 * @{
 */

/**
 * @addtogroup TIMER_DRV
 * @{
 */

/**
 * @addtogroup TIMER_DRV_Private_Macros
 * @{
 */

/**
 * @def IS_DRV_TIMER_CLK_DIV
 * @brief Check if __VALUE__ is TIMER Time out type
 */
#define IS_DRV_TIMER_CLK_DIV(__VALUE__)     (((__VALUE__) == DRV_TIMER_CLK_DIV_2) \
                                            || ((__VALUE__) == DRV_TIMER_CLK_DIV_32) \
                                            || ((__VALUE__) == DRV_TIMER_CLK_DIV_256) \
                                            || ((__VALUE__) == DRV_TIMER_CLK_DIV_2048))

/**
 * @def IS_DRV_TIMER_CNT_DIR
 * @brief Check if __VALUE__ is TIMER count direction type
 */
#define IS_DRV_TIMER_CNT_DIR(__VALUE__)     (((__VALUE__) == DRV_TIMER_COUNT_UP) \
                                            || ((__VALUE__) == DRV_TIMER_COUNT_DOWN))

/**
 * @def IS_DRV_TIMER_AUTO_LD
 * @brief Check if __VALUE__ is TIMER auto load type
 */
#define IS_DRV_TIMER_AUTO_LD(__VALUE__)     (((__VALUE__) == DRV_TIMER_ONE_SHOT) \
                                            || ((__VALUE__) == DRV_TIMER_AUTO_LD))

/**
 * @def IS_DRV_TIMER_CAP_MODE
 * @brief Check if __VALUE__ is TIMER capture mode type
 */
#define IS_DRV_TIMER_CAP_MODE(__VALUE__)    (((__VALUE__) == DRV_TIMER_AUTO_LD) \
                                            || ((__VALUE__) == DRV_TIMER_CAP_SECOND))

/**
 * @def IS_DRV_TIMER_CAP_EVENT
 * @brief Check if __VALUE__ is TIMER capture event type
 */
#define IS_DRV_TIMER_CAP_EVENT(__VALUE__)   (((__VALUE__) == DRV_TIMER_CAP_DIS) \
                                            || ((__VALUE__) == DRV_TIMER_CAP_H2L) \
                                            || ((__VALUE__) == DRV_TIMER_CAP_L2H) \
                                            || ((__VALUE__) == DRV_TIMER_CAP_BOTH))

/**
 * @def IS_DRV_TIMER_MODE
 * @brief Check if __VALUE__ is TIMER mode type
 */
#define IS_DRV_TIMER_MODE(__VALUE__)        (((__VALUE__) == DRV_TIMER_FREE_RUN) \
                                            || ((__VALUE__) == DRV_TIMER_USER_DEF))

/**
 * @def IS_DRV_PWM_TRI
 * @brief Check if __VALUE__ is TIMER pwm trigger type
 */
#define IS_DRV_PWM_TRI(__VALUE__)           (((__VALUE__) == DRV_TIMER_NO_TRI) \
                                            || ((__VALUE__) == DRV_TIMER_OF) \
                                            || ((__VALUE__) == DRV_TIMER_OF_MAT) \
                                            || ((__VALUE__) == DRV_TIMER_MAT))

/**
 * @def IS_DRV_PWM_OUT
 * @brief Check if __VALUE__ is TIMER pwm outs type
 */
#define IS_DRV_PWM_OUT(__VALUE__)           (((__VALUE__) == DRV_TIMER_OUT_PLU) \
                                            || ((__VALUE__) == DRV_TIMER_OUT_TOG))

/**
 * @def IS_DRV_PWM_PLUSE
 * @brief Check if __VALUE__ is TIMER pwm pluse type
 */
#define IS_DRV_PWM_PLUSE(__VALUE__)         (((__VALUE__) == DRV_TIMER_POS) \
                                            || ((__VALUE__) == DRV_TIMER_NEG))
/** @} TIMER_DRV_Private_Macros */


/**
 * @addtogroup TIMER_DRV_Exported_Functions
 * @{
 */

/**
 * @fn ErrorStatus DrvTimerDeInit(TimerTypedef* TIMERx)
 * @brief De-initialize TIMER registers
 * 
 * @param[in] TIMERx TIMER instance
 * @return TIMER is de-initialized or not
 * @retval kSuccess TIMER registers are de-initialized
 * @retval kError TIMER registers are not de-initialized
 */
ErrorStatus DrvTimerDeInit(TimerTypedef* TIMERx) {
  ErrorStatus status = kSuccess;
  /* Check the TIMER Instance TIMERx */
  assert_param(IS_TIMER_ALL_INSTANCE(TIMERx));
  if (TIMER0 == TIMERx) {
    CLEAR_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_TIMER);
    SET_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_TIMER);
  }
  else if (TIMER1 == TIMERx) {
    CLEAR_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_TIMER);
    SET_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_TIMER);
  }
  else if (TIMER2 == TIMERx) {
    CLEAR_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_TIMER);
    SET_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_TIMER);
  }
  else if (TIMER3 == TIMERx) {
    CLEAR_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_TIMER);
    SET_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_TIMER);
  }
  else {
    status = kError;
  }
  return status;
}


/**
 * @fn ErrorStatus DrvTimerInit(TimerTypedef* TIMERx, DrvTimerInitTypedef* timer_init_struct)
 * @brief Initialize TIMER registers according to the specified parameters in DrvTimerInitTypedef
 * 
 * @param[in] TIMERx TIMER instance
 * @param[in] timer_init_struct pointer to a DrvTimerInitTypedef structure that contians the 
 *            configuration information for the specified TIMER peripheral 
 * @return TIMER is initialized or not
 * @retval kSuccess TIMER registers are initialized according to timer_init_struct content
 * @retval kError Problem occured during TIMER registers initialization
 */
ErrorStatus DrvTimerInit(TimerTypedef* TIMERx, DrvTimerInitTypedef* timer_init_struct) {
  ErrorStatus status = kError;
  
  assert_param(IS_TIMER_ALL_INSTANCE(TIMERx));
  assert_param(IS_DRV_TIMER_CNT_DIR(timer_init_struct->timer_count_dir));
  assert_param(IS_DRV_TIMER_AUTO_LD(timer_init_struct->auto_load));
  assert_param(IS_DRV_TIMER_MODE(timer_init_struct->mode));
  
  
  if (!DrvTimerIsEnable(TIMERx)) {
    MODIFY_REG(TIMERx->CONTROL, TMR_CONTROL_UP_DWN | TMR_CONTROL_AUTO_LD | TMR_CONTROL_MODE ,
               timer_init_struct->timer_count_dir | timer_init_struct->auto_load | timer_init_struct->mode);
    WRITE_REG(TIMERx->LOAD_VALUE, timer_init_struct->load_value);
    status = kSuccess;
  }
  DrvTimerLoad(TIMERx);
  
  return status;
}


/**
 * @fn void DrvTimerStructInit(DrvTimerInitTypedef* timer_init_struct, uint32_t value)
 * @brief Set each @ref DrvTimerInitTypedef field to default value
 * 
 * @param[out] timer_init_struct pointer to a @ref DrvTimerInitTypedef structure
 *             whose field will be set to default values
 * @param[in]  value timer value
 * @return None
 */
void DrvTimerStructInit(DrvTimerInitTypedef* timer_init_struct, uint32_t value) {
  timer_init_struct->load_value           = value;
  timer_init_struct->timer_count_dir      = DRV_TIMER_COUNT_UP;
  timer_init_struct->auto_load            = DRV_TIMER_ONE_SHOT;
  timer_init_struct->mode                 = DRV_TIMER_FREE_RUN;
}
/** @} TIMER_DRV_Exported_Functions */
/** @} TIMER_DRV */
/** @} GT98xx_DRV */
